package application;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Map;

import vo.User;
import Utils.Constants;
import Utils.FileUtils;
import Utils.SortUtils;

public class FuzzyMath {

	// 模糊意见集中决策算法
	// 输入：待评价矩阵，评价对象
	// 输出：被评价对象的顺序
	public static Hashtable<String, Double> borda(double a, double b, double c, double d, String[][] opinions, ArrayList<String> objs) {
		Hashtable<String, Double> borda = new Hashtable<String, Double>();
		// 每个用户的初始borda数为0
		// Enumeration<String> en = borda.keys();
		for (int i = 0; i < objs.size(); i++)
			borda.put(objs.get(i), 0.0);

		int objSize = objs.size();
		for (int i = 0; i < opinions.length; i++) {
			for (int j = 0; j < opinions[i].length; j++) {
				for (int k = 0; k < objs.size(); k++) {
					String obj = objs.get(k);

					// 如果评价矩阵中某个元素和用户列表中元素相同
					if (opinions[i][j].equals(obj)) {
						// 用户的borda值+改评委给的分数
						if (i == 0)// 第一个评委
							borda.put(obj, borda.get(obj) + a * (objSize - j - 1));
						if (i == 1)// 第2个评委
							borda.put(obj, borda.get(obj) + b * (objSize - j - 1));
						if (i == 2)// 第3个评委
							borda.put(obj, borda.get(obj) + c * (objSize - j - 1));
						if (i == 3)// 第4个评委
							borda.put(obj, borda.get(obj) + d * (objSize - j - 1));
					}
				}
			}
		}
		return borda;
	}

	public static void computeBordaScore() {

		// 读取用户和各种值的映射
		Hashtable<String, Double> userId_activity = FileUtils.readHashtableD(Constants.USERID_ACTIVITY_PATH);
		Hashtable<String, Double> userId_stability = FileUtils.readHashtableD(Constants.USERID_STABILITY_PATH);
		Hashtable<String, Double> userId_content = FileUtils.readHashtableD(Constants.USERID_CONTENT_PATH);
		Hashtable<String, Double> userId_reliability = FileUtils.readHashtableD(Constants.USERID_RELIABILITY_PATH);

		// 计算各种分数的排名
		try {
			Map.Entry[] keys1 = SortUtils.sortedHashtableByValue(userId_activity, Constants.DESC);
			Map.Entry[] keys2 = SortUtils.sortedHashtableByValue(userId_stability, Constants.DESC);
			Map.Entry[] keys3 = SortUtils.sortedHashtableByValue(userId_content, Constants.DESC);
			Map.Entry[] keys4 = SortUtils.sortedHashtableByValue(userId_reliability, Constants.DESC);
			String keyStr1 = "";
			String keyStr2 = "";
			String keyStr3 = "";
			String keyStr4 = "";
			// 得到用户的排名，写入文件
			for (int i = 0; i < keys1.length; i++) {
				keyStr1 += keys1[i].getKey() + "\n";
				keyStr2 += keys2[i].getKey() + "\n";
				keyStr3 += keys3[i].getKey() + "\n";
				keyStr4 += keys4[i].getKey() + "\n";
			}
			FileUtils.write(Constants.root + "1.txt", keyStr1);
			FileUtils.write(Constants.root + "2.txt", keyStr2);
			FileUtils.write(Constants.root + "3.txt", keyStr3);
			FileUtils.write(Constants.root + "4.txt", keyStr4);

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public static Hashtable<String, Double> bordaRanking(double a, double b, double c, double d, ArrayList<String> userIds) {
		String[][] opinions = new String[Constants.WEIGHT_COUNT][userIds.size()];
		// 计算评价矩阵
		for (int i = 0; i < Constants.WEIGHT_COUNT; i++) {
			String path = Constants.root + (i + 1) + ".txt";
			String fileContent = FileUtils.readFile(path, Constants.FILE_ENCODING);
			String items[] = fileContent.split(Constants.LINE_SEPERATOR);
			// 读取排名文件，第i个专家心中的排名为items
			opinions[i] = items;// 一行是一个因素的分数
		}
		Hashtable<String, Double> borda = borda(a, b, c, d, opinions, userIds);
		FileUtils.writeFileHashtable(borda, "borda_ranking_" + a + "_" + b + "_" + c + "_" + d + ".txt", Constants.DESC);
		return borda;
	}

	public static ArrayList<User> getTopUserIdBorda(int topNumber) {
		ArrayList<User> users = new ArrayList<User>();
		// TODO:读取前十名
		return users;
	}

	// 计算带有权重的borda决策结果
	public static ArrayList<Double> weighedBorda(ArrayList<Double> weighs, double[][] opinions) {
		ArrayList<Double> borda = new ArrayList<Double>();

		for (int j = 0; j < opinions[0].length; j++) {

			double max = -1;
			for (int i = 0; i < weighs.size(); i++) {
				double min = Math.min(weighs.get(i), opinions[i][j]);
				if (max < min)
					max = min;
			}
			borda.add(max);

		}
		System.out.println("borda:" + borda);
		return borda;
	}

	// 加法
	public static double fuzzyAdd(ArrayList<Double> b1, ArrayList<Double> b2) {
		double max = -1;
		for (int i = 0; i < b1.size(); i++) {
			double min = Math.min(b1.get(i), b2.get(i));
			if (min > max)
				max = min;
		}
		System.out.println("模糊加法:" + max);
		return max;
	}

	// 模糊乘法
	public static double fuzzyMultiply(ArrayList<Double> b1, ArrayList<Double> b2) {
		double min = 2;
		for (int i = 0; i < b1.size(); i++) {
			double max = Math.max(b1.get(i), b2.get(i));
			if (max < min)
				min = max;
		}
		System.out.println("模糊乘法:" + min);
		return min;
	}

	public static double closeDegree(ArrayList<Double> b1, ArrayList<Double> b2) {
		double sum = fuzzyAdd(b1, b2);
		double product = fuzzyMultiply(b1, b2);
		double result = 0.5 * (sum + (1 - product));
		System.out.println(sum);
		System.out.println(product);
		System.out.println(result);
		return result;
	}

	public static double membershipMethod(double benchmark, int x) {
		double a = 0.01;
		double b = 2;
		double result = 0.0;
		if (x < benchmark) {
			result = (1) / (1 + a * Math.pow(x - benchmark, -b));
		} else {
		}
		return result;

	}

	public static void main(String[] args) {
		// 测试有权重的borda算法
		// ArrayList<Double> weighs = new ArrayList<Double>();
		// weighs.add(0.2);
		// weighs.add(0.4);
		// weighs.add(0.1);
		// weighs.add(0.3);
		// double[][] opinions = { { 0.3, 0.6, 0.1, 0 }, { 0, 0.2, 0.5, 0.3 }, {
		// 0.5, 0.3, 0.1, 0.1 }, { 0.1, 0.3, 0.2, 0.4 } };
		//
		// weighedBorda(weighs, opinions);
		// 计算fuzzy的加法和减法
		// ArrayList<Double> b1 = new ArrayList<Double>();
		// b1.add(0.2);
		// b1.add(0.3);
		// b1.add(0.4);
		// b1.add(0.3);
		// ArrayList<Double> b2 = new ArrayList<Double>();
		// b2.add(0.2);
		// b2.add(0.2);
		// b2.add(0.4);
		// b2.add(0.3);
		//
		// closeDegree(b1, b2);
		// 计算隶属度
		// System.out.println(membershipMethod(60, 20));
		// System.out.println(membershipMethod(60, 40));
		// System.out.println(membershipMethod(60, 50));
		// System.out.println(membershipMethod(60, 100));

	}

}
